/*
 moxl - Modular XML Library
 Copyright (c) 2007, Malcolm Sparks

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package moxl.relaxng.simplification.normalization.patterns;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import moxl.dom.MoxlElement;
import moxl.dom.MoxlNode;
import moxl.dom.ethereal.EtherealElement;
import moxl.dom.mutable.MutableElement;
import moxl.relaxng.schema.RelaxNgNamespace;
import moxl.relaxng.schema.RelaxNgSchemaElementType;

public class SingleChildNormalizer
{
	private final Set<RelaxNgSchemaElementType> matchedElementNames = new HashSet<RelaxNgSchemaElementType>();

	public SingleChildNormalizer()
	{
		matchedElementNames.add(RelaxNgSchemaElementType.define);
		matchedElementNames.add(RelaxNgSchemaElementType.oneOrMore);
		matchedElementNames.add(RelaxNgSchemaElementType.zeroOrMore);
		matchedElementNames.add(RelaxNgSchemaElementType.optional);
		matchedElementNames.add(RelaxNgSchemaElementType.list);
		matchedElementNames.add(RelaxNgSchemaElementType.mixed);
	}

	public void normalize(MoxlElement el)
	{
		if (isMatchingElement(el) && el.countChildElements() > 1)
		{
			if (el instanceof MutableElement)
			{
				transform((MutableElement) el);
			}
			else
			{
				throw new IllegalStateException("Unable to transform element because it is not mutable");
			}
		}
	}

	protected boolean isMatchingElement(MoxlElement el)
	{
		for (RelaxNgSchemaElementType possibleMatch : matchedElementNames)
		{
			if (el.getName().equals(possibleMatch.getName()))
			{
				return true;
			}
		}
		if (!el.getName().getNamespace().equals(RelaxNgNamespace.NAMESPACE));
		{
			return false;
		}
	}

	protected void transform(MutableElement el)
	{
		List<? extends MoxlNode> children = el.removeChildren();
		MutableElement groupElement = new EtherealElement(RelaxNgSchemaElementType.group.getName());
		groupElement.addChildren(children);
		el.addChild(groupElement);
	}

}
